<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2019/1/8
 * Time: 16:39
 */

namespace api\storage\service\input;

use api\storage\common\Constant;
use api\storage\exception\UnsupportedOperationException;
use api\storage\model\InflowModel;
use api\storage\model\PurchaseDetailModel;
use api\storage\model\ReelsModel;
use api\storage\model\SeatModel;
use api\storage\model\ShelvesModel;
use api\storage\model\SmtMaterielModel;
use api\storage\model\SubMaterielModel;
use api\storage\service\BaseService;
use api\storage\service\InflowService;
use api\storage\service\ReelsService;
use api\storage\service\SocketService;
use service\logger\LoggerFactory;
use think\Db;
use think\Debug;

abstract class BaseInputService extends BaseService
{

    protected $shelvesModel;
    protected $materielId;
    protected $count;
    protected $logger;
    protected $smtMaterielModel;

    public function __construct()
    {
        $this->shelvesModel = new ShelvesModel();
        $this->logger = LoggerFactory::getLogger('input');
        $this->smtMaterielModel = new SmtMaterielModel();
    }

    /**
     * 参数检查
     *
     * @param $reelId
     * @param $userId
     * @param $storageUuid
     * @return array|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function check($reelId, $userId, $storageUuid)
    {
        //查看物料是否在purchase表
        $purchaseModel = new PurchaseDetailModel();
        $purchase = $purchaseModel->findByReelId($reelId);
        if ($this->isEmpty($purchase)) {
            return $this->resultTemplate(-2);
        }
        $materielId = $purchase->getData('sub_materiel_id');
        //查看物料是否已经上架
        $reelsModel = new ReelsModel();
        $reels = $reelsModel->findReelByIdAndUuid($reelId, $storageUuid);
        if ($this->isNotEmpty($reels)) {
            return $this->resultTemplate(3, $this->dataTemplate($materielId, $reels->getData('seat_code'), $reels->getData('count')));
        }


        $materielModel = new SubMaterielModel();
        $materiel = $materielModel->findByMaterielId($materielId);
        //判断物料是否存在
        if (empty($materiel)) {
            return $this->resultTemplate(4);
        }
        $type = $materielModel->findTypeByMaterielId($materielId);
        //判断物料是否选择过类型
        if (empty($type)) {
            return $this->resultTemplate(2, $this->dataTemplate($materielId, '', 0));
        }
        //C类不是选择站位
        if (strtoupper($type) == Constant::SHELF_TYPE_OF_CONTAINER) {
            return $this->resultTemplate(-1);
        }
        $this->materielId = $materielId;
        $this->count = $purchase->getData('count');
        $this->count = empty($this->count) ? 0 : intval($this->count);
        return $this->afterHandle($userId, $type, $storageUuid);
    }


    /**
     * @param $reelId
     * @param $seatCode
     * @param $storageUuid
     * @param $nickname
     * @return array|mixed
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     * @throws \Exception
     */
    public function putInfoShelf($reelId, $seatCode, $storageUuid, $nickname)
    {
        Debug::remark("begin");
        $purchaseModel = new PurchaseDetailModel();
        $purchase = $purchaseModel->findByReelId($reelId);
        $ret = $this->checkSeatCode($seatCode, $storageUuid);
        if ($ret['status'] <= 0) {
            return $ret;
        }
        $reelsModel = new ReelsModel();
        $reelsModel->startTrans();
        $reels = $reelsModel->findByIdAndUuidWithLock($reelId, $storageUuid);
        if (empty($reels)) {
            //新料
            $reelInfo = ReelsService::generateReels($reelId, $purchase->getData('sub_materiel_id'),
                $purchase->getData('count'), $seatCode, '', $storageUuid);
            $reelsRes = $reelsModel->add($reelInfo);


            if($reelInfo['storage_uuid'] == "184928afb9e35f3ff421da05fc3f917f"){//如果是smt入库
                $this->smtMaterielModel->startTrans();
                $smtMaterielObj = $this->smtMaterielModel->findByLock(['sub_materiel_id' => $reelInfo['sub_materiel_id']]);
                if (empty($smtMaterielObj)){
                    $data = [
                        'uuid' => md5(create_uuid()),
                        'sub_materiel_id'=> $reelInfo['sub_materiel_id'],
                        'total_num' => $reelInfo['count'],
                        'simulation_num' => $reelInfo['count']
                    ];
                    $this->smtMaterielModel->add($data);
                    $this->smtMaterielModel->commit();
                }
                else{
                    $smtMateriel = $smtMaterielObj->toArray();
                    $data = [
                        'total_num' => $smtMateriel['total_num'] + $reelInfo['count'],
                        'simulation_num' => $smtMateriel['simulation_num'] + $reelInfo['count'],
                    ];
                    $this->smtMaterielModel->updateMaterielWithLock($data,['sub_materiel_id' => $reelInfo['sub_materiel_id']]);
                    $this->smtMaterielModel->updateCheckTime(['sub_materiel_id' => $reelInfo['sub_materiel_id']]);
                    $this->smtMaterielModel->commit();
                }

            }

        } else {
            //旧料
            $saveData = ReelsService::generateUpdateReels($purchase->getData('count'), $seatCode);
            $reelsRes = $reelsModel->updateReel($reelId, $storageUuid, $saveData);
            //将数据合并一下，$saveData覆盖之前的数据
            $reelInfo = array_merge($reels->getData(), $saveData);

        }
        //将站位占用
        $seatModel = new SeatModel();
        $seatRes = $seatModel->updateIsUsed($seatCode, $storageUuid);
        //记录入库流水
        $inflowModel = new InflowModel();

        $insertData = InflowService::generateInflow($reelInfo, $nickname);
        $inflowRes = $inflowModel->add($insertData);

        //事务判断
        Debug::remark("end");
        $this->logger->info('入库耗时：' . Debug::getRangeTime('begin', 'end') . 's');
        if (empty($reelsRes) || $seatRes === false || empty($inflowRes)) {
            $reelsModel->rollback();
            return $this->resultTemplate(0);
        } else {
            SocketService::send($ret['data']['seat_id'], $storageUuid, Constant::TURN_OFF_LIGHT);
            $reelsModel->commit();
            return $this->resultTemplate(1);
        }
    }

    public function lookingBindShelf($userId, $storageUuid)
    {
        throw new UnsupportedOperationException("不支持查看绑定货架");
    }

    public function bindShelf($seatCode, $userId, $storageUuid)
    {
        throw new UnsupportedOperationException("不支持绑定货架");
    }

    public function unbindShelf($userId, $storageUuid)
    {
        throw new UnsupportedOperationException("不支持解除绑定货架");
    }

    /**
     * 检查后的其他处理
     *
     * @param $userId
     * @param $type
     * @param $storageUuid
     * @return mixed
     */
    protected abstract function afterHandle($userId, $type, $storageUuid);

    /**
     * 检查站位情况
     *
     * @param $seatCode
     * @param $storageUuid
     * @return mixed
     */
    protected abstract function checkSeatCode($seatCode, $storageUuid);

    protected function dataTemplate($materielId, $seatCode, $count)
    {
        return [
            'subMaterielId' => $materielId,
            'seatCode' => $seatCode,
            'count' => $count
        ];
    }


}